#pragma once
#include <vector>
#include "fnv1a.h"
#include "UtlLinkedList.h"
#include <unordered_map>
#include "../../vector/Vector.h"

union CvarValueTypes 
{
	bool Bool;
	short Int16;
	uint16_t Uint16;
	int Int;
	uint32_t Uint32;
	int64_t Int64;
	uint64_t Uint64;
	float Float;
	double Double;
	const char* String;
	uint8_t Color[4];
	Vector3 Vector2D;
	Vector3 Vector3D;
	Vector3 Vector4D;
	Vector3 Angles;
};

class CConVar 
{
public:
	const char* szName;
	CConVar* m_pNext;
	char pad_0[0x10];
	const char* szDescription;
	uint32_t nType;
	uint32_t nRegistered;
	uint32_t nFlags;
	//std::uint32_t m_unk3;
	//std::uint32_t m_nCallbacks;
	//std::uint32_t m_unk4;
	char pad_1[0x10]; // 0x34
	CvarValueTypes Value;
	CvarValueTypes ValueOld;
	template <typename T>
	T GetValue() {
		return *reinterpret_cast<T*>(&Value);
	}
};

inline std::unordered_map<uint64_t, CConVar*> mapCvars = {};
class IEngineCvar 
{
	char pad_0[0x40];
	CUtlLinkedList<CConVar*> listConvars;
public:
	static IEngineCvar* Get() 
	{
		static IEngineCvar* pEngineCvar = reinterpret_cast<IEngineCvar*>(Memory::CreateInterface("tier0.dll", "VEngineCvar007"));
		return pEngineCvar;
	}

	CConVar* Find(std::string szCvarName)
	{
		for (int i = listConvars.Head(); i != listConvars.InvalidIndex(); i = listConvars.Next(i)) 
		{
			CConVar* pConVar = listConvars.Element(i);
			if (pConVar == nullptr)
				continue;

			if (HASH_RT(pConVar->szName) == HASH_RT(szCvarName.c_str()))
				return pConVar;
		}
		return nullptr;
	}
};
